package com.whosly.fast.web.quickly.filter;

import com.whosly.fast.web.quickly.handler.LocalCachehandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.Objects;

/**
 * 由于可能涉及多个反应式流（Reactor streams），直接在过滤器中阻塞等待计数可能不是最佳实践。
 * 相反，可以使用反应式编程的概念来处理限流。
 *
 * WebFilter 以链式拦截方式处理 Web 请求。WebFilter 在全局范围内生效，一旦启用，将拦截所有的请求和响应。
 */
@Component
@Order(-10)
public class RateLimitWebFilter implements org.springframework.web.server.WebFilter {
    private static final Logger logger = LoggerFactory.getLogger(RateLimitWebFilter.class);

    // 假设每个IP每分钟最多50次请求
    private static final int MAX_REQUESTS_PER_MINUTE = 60;

    private final ReactiveRateLimiter rateLimiter;

    public RateLimitWebFilter(LocalCachehandler cachehandler) {
        this.rateLimiter = new ReactiveRateLimiter(cachehandler,
                MAX_REQUESTS_PER_MINUTE, Duration.ofMinutes(1));
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        // 在请求处理之前执行
        System.out.println("Before request is processed");
        ServerHttpRequest request = exchange.getRequest();

        PathPattern pattern = new PathPatternParser().parse("/monitor/w/**");
        if (pattern.matches(request.getPath().pathWithinApplication())){
            System.out.println("custom /service webFilter");
        }

        String ipAddress = extractIpAddress(request);

        return rateLimiter.tryAcquire(ipAddress)
                .flatMap(acquired -> {
                    if (acquired) {
                        // 继续处理请求
                        return chain.filter(exchange)
                                .then(Mono.fromRunnable(() -> {
                                    // 在请求处理之后执行
                                    System.out.println("After request is processed");
                                }));
                    } else {
                        // 处理限流逻辑，例如返回429 Too Many Requests
                        ServerHttpResponse response = exchange.getResponse();
                        response.setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
                        return response.setComplete();
                    }
                });
    }

    private String extractIpAddress(ServerHttpRequest req) {
        try {
            String ip = Objects.requireNonNull(req.getRemoteAddress()).getAddress().getHostAddress();

            return ip;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}
